package utils;

import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import utils.csv.annotation.CsvIngore;
import utils.csv.annotation.CsvProperty;
import utils.csv.reflect.CsvField;

import java.io.File;
import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class XlsUtils {

    public static <T> void exportXLS(List<T> dataList, String fileDir,String fileName) throws Exception {
        if (dataList == null || dataList.size() == 0) {
            throw new IllegalArgumentException("dataList不能为空");
        }
        File dir =  new File(fileDir);
        if(!dir.exists() || !dir.isDirectory())throw new Exception("路径不存在,或者不是一个文件夹!");
        String tempPath = new StringBuffer(fileDir).append(File.separator).append("temp").append(File.separator).toString();
        String filePath = new StringBuffer(fileDir).append(File.separator).append(fileName).toString();
        File tempFilePath = new File(tempPath);
        if(!tempFilePath.exists())tempFilePath.mkdirs();
        File file = new File(filePath);
        List<CsvField> csvFields = getFieldList(dataList.get(0).getClass());

        WorkbookSettings workbookSettings = new WorkbookSettings();
        workbookSettings.setUseTemporaryFileDuringWrite(true);
        workbookSettings.setTemporaryFileDuringWriteDirectory(tempFilePath);
        WritableWorkbook wwb = Workbook.createWorkbook(file,workbookSettings);
        WritableSheet ws = wwb.createSheet("Sheet 1", 0);

        for (int c = 0; c < csvFields.size(); c++) {
            CsvField csvField = csvFields.get(c);
            String alias = csvField.getField().getAnnotation(CsvProperty.class).alias();
            if (alias == null) {
                alias = csvField.getField().getName();
            }
            Label label = new Label(c, 0, (alias != null) ? alias : "");
            ws.addCell(label);
        }
        for (int r = 0; r < dataList.size(); r++) {
            T t = dataList.get(r);
            for (int c = 0; c < csvFields.size(); c++) {
                CsvField csvField = csvFields.get(c);
                String datePattern = csvField.getField().getAnnotation(CsvProperty.class).datePattern();
                boolean isAmount = csvField.getField().getAnnotation(CsvProperty.class).isAmount();
                Object value = Reflections.getFieldValue(t, csvField.getField().getName());
                if (datePattern != null && !"".equals(datePattern) && value != null && !"".equals(value)) {
                    value = DateUtils.formatDate( datePattern,(Date) value);
                }
                if (isAmount == true && value != null && !"".equals(value)) {
                    NumberFormat ddf = NumberFormat.getNumberInstance();
                    ddf.setMinimumFractionDigits(2);
                    value = ddf.format((int) value * 0.01);
                }
                Label label = new Label(c, r + 1, (value != null) ? value.toString() : "");
                ws.addCell(label);
            }
        }
        wwb.write();
        wwb.close();
    }



    private static <T> List<CsvField> getFieldList(Class<T> clazz) {
        int defaultOrder = -1;
        List<CsvField> csvFields = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            if (f.getAnnotation(CsvIngore.class) != null && f.getAnnotation(CsvIngore.class).value()) continue;
            if (f.getAnnotation(CsvProperty.class) == null) continue;
            Integer order = 0;
            Boolean notIgnore = false;
            Boolean isAmout = false;
            CsvProperty csvPropertyAnno = f.getAnnotation(CsvProperty.class);
            if (csvPropertyAnno != null) {
                order = csvPropertyAnno.order();
                if (order != null && order < 0)
                    throw new IllegalArgumentException(f.getClass().getName() + "." + f.getName() + "() @CsvProperty order必须大于0");
                if (order == null || order == 0) order = defaultOrder -= 1;
                notIgnore = csvPropertyAnno.notIgnore();
                isAmout = csvPropertyAnno.isAmount();
            } else order = defaultOrder -= 1;
            csvFields.add(new CsvField(order, f, isAmout, notIgnore));
        }
        csvFields.sort((f1, f2) -> f2.getOrder() - f1.getOrder());
        return csvFields;
    }
}
